package cn.ibizlab.modeling.addin.modelinglibrary.plugin.groovy.sysutil;

import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.util.ObjectUtils
import org.springframework.util.StringUtils

import groovy.transform.CompileStatic;
import net.ibizsys.central.dataentity.IDataEntityRuntime
import net.ibizsys.central.dataentity.action.IDEActionPluginRuntime2
import net.ibizsys.central.dataentity.service.DEMethodPluginRuntimeRepo
import net.ibizsys.central.service.client.IWebClientRep
import net.ibizsys.central.service.client.WebClientBase
import net.ibizsys.central.util.IEntityDTO
import net.ibizsys.central.util.ISearchContextDTO
import net.ibizsys.central.util.PageImpl
import net.ibizsys.model.dataentity.action.IPSDEAction
import net.ibizsys.model.dataentity.ds.IPSDEDataSet
import net.ibizsys.runtime.dataentity.IDataEntityRuntimeContext
import net.ibizsys.runtime.dataentity.ds.IDEDataSetPluginRuntime
import net.ibizsys.runtime.util.ActionSessionManager
import net.ibizsys.runtime.util.DataTypeUtils
import net.ibizsys.runtime.util.IAppContext

@CompileStatic
class LibrarySysUtilRuntime extends net.ibizsys.central.cloud.core.sysutil.SysUtilRuntimeBase {
	private static final org.apache.commons.logging.Log log = LogFactory.getLog(LibrarySysUtilRuntime.class);
	
	private DEMethodPluginRuntimeRepo deMethodPluginRuntimeRepo = new DEMethodPluginRuntimeRepo();
	
	final static String DEMODEL_MODEL_LIBRARY = "MODEL_LIBRARY";
	
	final static String DEMODEL_MODEL_CATEGORY = "MODEL_CATEGORY";
	
	final static String DEMODEL_MODEL_TEMPLATE = "MODEL_TEMPLATE";
	
	
	final static String DEDATASET__MODEL_CATEGORY__ROOT = "ROOT";
	final static String DEDATASET__MODEL_CATEGORY__DEFAULT = "DEFAULT";
	final static String DEDATASET__MODEL_TEMPLATE__DEFAULT = "DEFAULT";
	final static String DEACTION__MODEL_TEMPLATE__GET = "GET";
	
	@Qualifier(DEMODEL_MODEL_LIBRARY)
	private IDataEntityRuntime libraryDataEntityRuntime = null;
	
	@Qualifier(DEMODEL_MODEL_CATEGORY)
	private IDataEntityRuntime categoryDataEntityRuntime = null;
	
	@Qualifier(DEMODEL_MODEL_TEMPLATE)
	private IDataEntityRuntime templateDataEntityRuntime = null;
	
	
	@Override
	protected void onInit() throws Exception {
		this.deMethodPluginRuntimeRepo.init(this.getSystemRuntime(), true);
		super.onInit();
	}
	
	protected DEMethodPluginRuntimeRepo getDEMethodPluginRuntimeRepo() {
		return this.deMethodPluginRuntimeRepo;
	}
	
	@Override
	protected void onInstall() throws Exception {
		super.onInstall();
		
		this.onRegisterDEMethodPluginRuntimes();
	}
	
	protected void onRegisterDEMethodPluginRuntimes() throws Exception{
		this.getDEMethodPluginRuntimeRepo().registerDEDataSetPluginRuntimeIf(DEMODEL_MODEL_CATEGORY, DEDATASET__MODEL_CATEGORY__ROOT, new IDEDataSetPluginRuntime() {

			@Override
			public Object fetch(IDataEntityRuntimeContext iDataEntityRuntimeContext, IPSDEDataSet iPSDEDataSet, Object[] args, Object actionData) throws Throwable {
				return doFetchCategories((ISearchContextDTO)args[0], true);
			}
			
		});
	
		this.getDEMethodPluginRuntimeRepo().registerDEDataSetPluginRuntimeIf(DEMODEL_MODEL_CATEGORY, DEDATASET__MODEL_CATEGORY__DEFAULT, new IDEDataSetPluginRuntime() {
		
			@Override
			public Object fetch(IDataEntityRuntimeContext iDataEntityRuntimeContext, IPSDEDataSet iPSDEDataSet, Object[] args, Object actionData) throws Throwable {
				return doFetchCategories((ISearchContextDTO)args[0], false);
			}	
		});
	
		this.getDEMethodPluginRuntimeRepo().registerDEDataSetPluginRuntimeIf(DEMODEL_MODEL_TEMPLATE, DEDATASET__MODEL_TEMPLATE__DEFAULT, new IDEDataSetPluginRuntime() {
		
			@Override
			public Object fetch(IDataEntityRuntimeContext iDataEntityRuntimeContext, IPSDEDataSet iPSDEDataSet, Object[] args, Object actionData) throws Throwable {
				return doFetchTemplates((ISearchContextDTO)args[0]);
			}
		});
	
		this.getDEMethodPluginRuntimeRepo().registerDEActionPluginRuntime(DEMODEL_MODEL_TEMPLATE, DEACTION__MODEL_TEMPLATE__GET, new IDEActionPluginRuntime2() {
			@Override
			public Object execute(IDataEntityRuntimeContext iDataEntityRuntimeContext, IPSDEAction iPSDEAction,	Object[] args, Object actionData) throws Throwable {
				return doGetTemplate((String)args[0]);
			}
		});
	}
	
	protected Object doFetchCategories(ISearchContextDTO iSearchContextDTO, boolean root) throws Throwable{
		
		//查询应用上下文
		String strModelLibraryId = null;
		IAppContext iAppContext = ActionSessionManager.getAppContext();
		if(iAppContext != null) {
			strModelLibraryId = iAppContext.get(DEMODEL_MODEL_LIBRARY);
		}
		else {
			strModelLibraryId = iSearchContextDTO.get("n_model_library_id");
		}
		
		if(ObjectUtils.isEmpty(strModelLibraryId)) {
			throw new Exception("未指定模型仓库标识");
		}
		
		IEntityDTO library = libraryDataEntityRuntime.get(strModelLibraryId);
		String strLibraryPath = library.get("path");
		if(ObjectUtils.isEmpty(strLibraryPath)) {
			throw new Exception("模型仓库未指定路径");
		}
		
		String strCategoryPid = null;
		if(!root) {
			strCategoryPid = iSearchContextDTO.get("n_category_pid_eq");
			if(StringUtils.hasLength(strCategoryPid)) {
				strCategoryPid = java.net.URLDecoder.decode(strCategoryPid, "UTF-8");
			}
		}
			
		IWebClientRep<String> rep;
		try {
			String strUrl = "${strLibraryPath}/repository/tree";
			Map<String, String> uriQueries = new LinkedHashMap();
			if(!root) {
				strUrl += "?path={path}"
				uriQueries.put("path", strCategoryPid);
			}
			rep = this.getSystemRuntime().getDefaultWebClient().get(strUrl, uriQueries);
		} catch (Throwable ex) {
			throw new Exception(String.format("请求仓库发生异常，%1\$s", ex.getMessage()), ex);
		}
			
		int nTotal = DataTypeUtils.getIntegerValue(rep.getHeader("X-Total"), 0);
		List list = WebClientBase.getInputMapper().readValue(rep.getBody(), List.class);
		
		List<IEntityDTO> categoryList = new ArrayList<IEntityDTO>();
			
		for(Object objItem : list) {
			if(!(objItem instanceof Map)) {
				continue;
			}
				
			Map item = (Map)objItem;
			String strType = item.get("type");
			if(!"tree".equals(strType)) {
				continue;
			}
			
			String strPath = item.get("path");
			String strName = item.get("name");
			
			IEntityDTO category = categoryDataEntityRuntime.createEntity();
			category.set("category_id", java.net.URLEncoder.encode(strPath, "UTF-8"));
			category.set("category_name", strName)
			category.set("library_id", strModelLibraryId);
			if(StringUtils.hasLength(strCategoryPid)) {
				category.set("category_pid", java.net.URLEncoder.encode(strCategoryPid, "UTF-8"));
			}
			
			categoryList.add(category);
		}
		
		
		
		return new PageImpl(categoryList, iSearchContextDTO.getPageable(), categoryList.size());
	}
	
	protected Object doFetchTemplates(ISearchContextDTO iSearchContextDTO) throws Throwable{
		
		//查询应用上下文
		String strModelLibraryId = null;
		IAppContext iAppContext = ActionSessionManager.getAppContext();
		if(iAppContext != null) {
			strModelLibraryId = iAppContext.get(DEMODEL_MODEL_LIBRARY);
		}
		else {
			strModelLibraryId = iSearchContextDTO.get("n_model_library_id");
		}
		
		if(ObjectUtils.isEmpty(strModelLibraryId)) {
			throw new Exception("未指定模型仓库标识");
		}
		
		IEntityDTO library = libraryDataEntityRuntime.get(strModelLibraryId);
		String strLibraryPath = library.get("path");
		if(ObjectUtils.isEmpty(strLibraryPath)) {
			throw new Exception("模型仓库未指定路径");
		}
		
		String strCategoryId = iSearchContextDTO.get("n_category_id_eq");
		if(StringUtils.hasLength(strCategoryId)) {
			strCategoryId = java.net.URLDecoder.decode(strCategoryId, "UTF-8");
		}
		
		IWebClientRep<String> rep;
		try {
			String strUrl = "${strLibraryPath}/repository/tree";
			Map<String, String> uriQueries = new LinkedHashMap();
			if(!ObjectUtils.isEmpty(strCategoryId)) {
				strUrl += "?path={path}"
				uriQueries.put("path", strCategoryId);
			}
			rep = this.getSystemRuntime().getDefaultWebClient().get(strUrl, uriQueries);
		} catch (Throwable ex) {
			throw new Exception(String.format("请求仓库发生异常，%1\$s", ex.getMessage()), ex);
		}
			
		int nTotal = DataTypeUtils.getIntegerValue(rep.getHeader("X-Total"), 0);
		List list = WebClientBase.getInputMapper().readValue(rep.getBody(), List.class);
		
		List<IEntityDTO> templateList = new ArrayList<IEntityDTO>();
			
		for(Object objItem : list) {
			if(!(objItem instanceof Map)) {
				continue;
			}
				
			Map item = (Map)objItem;
			String strType = item.get("type");
			if(!"blob".equals(strType)) {
				continue;
			}
			
			String strPath = item.get("path");
			String strName = item.get("name");
			
			IEntityDTO template = templateDataEntityRuntime.createEntity();
			template.set("template_id", java.net.URLEncoder.encode(strPath, "UTF-8"));
			template.set("template_name", strName)
			if(StringUtils.hasLength(strCategoryId)) {
				template.set("category_id", java.net.URLEncoder.encode(strCategoryId, "UTF-8"));
			}
			template.set("library_id", strModelLibraryId);
			
			templateList.add(template);
		}
		
		return new PageImpl(templateList, iSearchContextDTO.getPageable(), templateList.size());
	}
	
	protected Object doGetTemplate(String key) throws Throwable{
		
		key = java.net.URLDecoder.decode(key, "UTF-8");
		
		//查询应用上下文
		String strModelLibraryId = null;
		IAppContext iAppContext = ActionSessionManager.getAppContext();
		if(iAppContext != null) {
			strModelLibraryId = iAppContext.get(DEMODEL_MODEL_LIBRARY);
		}
		
		if(ObjectUtils.isEmpty(strModelLibraryId)) {
			throw new Exception("未指定模型仓库标识");
		}
		
		IEntityDTO library = libraryDataEntityRuntime.get(strModelLibraryId);
		String strLibraryPath = library.get("path");
		if(ObjectUtils.isEmpty(strLibraryPath)) {
			throw new Exception("模型仓库未指定路径");
		}
		
		IWebClientRep<String> rep;
		try {
			String strRealKey = java.net.URLEncoder.encode(key, "UTF-8");
			String strUrl = "${strLibraryPath}/repository/files/{key}?ref={ref}";
			Map<String, String> uriQueries = new LinkedHashMap();
			uriQueries.put("key", key);
			uriQueries.put("ref", "HEAD");
			rep = this.getSystemRuntime().getDefaultWebClient().get(strUrl, uriQueries);
		} catch (Throwable ex) {
			throw new Exception(String.format("请求仓库发生异常，%1\$s", ex.getMessage()), ex);
		}
		
		if (rep != null) {
			try {
				Map item = WebClientBase.getInputMapper().readValue(rep.getBody(), Map.class);
				String content = (String) item.get("content");
				if (StringUtils.hasLength(content)) {
					content = new String(Base64.getDecoder().decode(content));
				}
				
				String strName = item.get("file_name");
				String strPath = item.get("file_path");
				
				IEntityDTO template = templateDataEntityRuntime.createEntity();
				template.set("template_id", java.net.URLEncoder.encode(strPath, "UTF-8"));
				template.set("template_name", strName)
				template.set("library_id", strModelLibraryId);
				template.set("dsl_content", content);
				
				return template;
			} catch (Exception ex) {
				throw new Exception(String.format("解析文件发生异常，%1\$s", ex.getMessage()), ex);
			}
		}
		else {
			throw new Exception(String.format("返回对象无效"));
		}
	}
	
	@Override
	protected void onUninstall() throws Throwable {
		this.getDEMethodPluginRuntimeRepo().shutdown();
		super.onUninstall();
	}
	
	
}
